package AlgoritmosGeneticos.model.impl;


import java.util.ArrayList;
import java.util.List;

import utils.CustomRandom;
import AlgoritmosGeneticos.model.AlgoritmoGenetico;
import AlgoritmosGeneticos.model.EstrategiaDeSeleccion;
import AlgoritmosGeneticos.model.Individuo;
import AlgoritmosGeneticos.model.Poblacion;
import AlgoritmosGeneticos.model.PoblacionSeleccionada;

public class PoblacionImpl implements Poblacion, AlgoritmoGenetico{

	private List<Individuo> individuos = new ArrayList<Individuo>();
	private  int popSize;
	private int k;						
	public static fitness fitness;
	
	public PoblacionImpl(int popSize, int k, double pMut, fitness fitness) {
		this.popSize = popSize;
		this.k = k;
		PoblacionImpl.fitness=fitness;
		
		for( int i = 0; i < popSize; i++){
			String indi = "";
			for(int j = 0; j < 16; j++){
				double rand = CustomRandom.getInstance().getDoubleRandom() ;
				if( rand < 0.5){
					indi +="1";
				}else{
					indi +="0";
				}
			}
			individuos.add(new IndividuoImpl(indi,pMut));
		}
	}

	@Override
	public PoblacionSeleccionada seleccionar(EstrategiaDeSeleccion estSel) {
		PoblacionSeleccionada pob = estSel.seleccionar(this.individuos, k);
		return pob;
	}

	@Override
	public void reemplazar( PoblacionSeleccionada pobsel, EstrategiaDeSeleccion estSel) {
		individuos.addAll(pobsel.getDescendencia());
		PoblacionSeleccionada pob =  estSel.seleccionar(individuos, popSize);
		this.individuos = pob.getProgenitores();
	}
	
	public static double aptitud(Individuo individuo){
		double numero = individuo.toNumber();
		double apto=Math.sin(10*numero)*Math.exp(-numero) + 4;
		
		if(PoblacionImpl.fitness.equals(AlgoritmoGenetico.fitness.MAXIMO))
			return apto;
		else{
			return 1f/apto;
		}
	}
	
	@Override
	public List<Individuo> getIndividuos(){
		return individuos;
	}
	
	public int getPopSize() {
		return popSize;
	}
}
